package sk.funix.userstory.service.impl;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AuthorizationServiceException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import sk.funix.userstory.config.security.SecurityUtil;
import sk.funix.userstory.dao.StoryDAO;
import sk.funix.userstory.domain.Story;
import sk.funix.userstory.domain.User;
import sk.funix.userstory.service.StoryService;



/**
 * @author Nicolas Milliard
 *
 */
@Service
public class StoryServiceImpl implements StoryService  {

	private static final Logger logger = LoggerFactory.getLogger(StoryServiceImpl.class);

	@Autowired
	private StoryDAO storyDAO;
	

	public StoryServiceImpl(){
		
	}
	
	/**
	 * @param storyDAO
	 */
	public StoryServiceImpl(StoryDAO storyDAO) {
		this.storyDAO = storyDAO;
	}


	/* (non-Javadoc)
	 * @see sk.funix.userstory.service.impl.StoryService#addNewStory(sk.funix.userstory.domain.Story)
	 */
	@Transactional
	public Story addNewStory(Story story) {
		checkSecurity(story.getUser());
		return storyDAO.makePersistent(story);
	}
	

	/* (non-Javadoc)
	 * @see sk.funix.userstory.service.impl.StoryService#updateAnStory(sk.funix.userstory.domain.Story)
	 */
	@Transactional
	public void updateAnStory(Story story) {
		checkSecurity(story.getUser());
		storyDAO.makePersistent(story);
	}


	/* (non-Javadoc)
	 * @see sk.funix.userstory.service.impl.StoryService#deleteAnStory(sk.funix.userstory.domain.Story)
	 */
	@Transactional
	public void deleteAnStory(Story story) {
		checkSecurity(story.getUser());
		storyDAO.makeTransient(story);
	}
	
	/* (non-Javadoc)
	 * @see sk.funix.userstory.service.impl.StoryService#deleteAnStoryById(java.lang.Long)
	 */
	@Transactional
	public void deleteAnStoryById(Long id) {
		Story story = storyDAO.findById(id, false);
		checkSecurity(story.getUser());
		storyDAO.makeTransient(story);
	}


	/* (non-Javadoc)
	 * @see sk.funix.userstory.service.impl.StoryService#findStoryById(java.lang.Long)
	 */
	@Transactional(readOnly = true)
	public Story findStoryById(Long id) {
		Story story = storyDAO.findById(id, false);
		checkSecurity(story.getUser());
		return story;
	}


	/* (non-Javadoc)
	 * @see sk.funix.userstory.service.impl.StoryService#findAllStorys()
	 */
	@Transactional(readOnly = true)
	public List<Story> findAllStories() {
		return storyDAO.findAll();
	}
	
	@Transactional(readOnly = true)
	public List<Story> findAllStoriesByUser(User user) {
		checkSecurity(user);
		return storyDAO.findAllStoriesByUser(user);
	}
	
	@Transactional(readOnly = true)
	public List<Story> findEntriesStoriesByUser(User user, int firstResult, int maxResults) {
		checkSecurity(user);
		return storyDAO.findEntriesStoriesByUser(user, firstResult, maxResults);
	}
	
	/* (non-Javadoc)
	 * @see sk.funix.userstory.service.impl.StoryService#findStorysEntries(int, int)
	 */
	@Transactional(readOnly = true)
	public List<Story> findStorysEntries(int firstResult, int maxResults) {
		return storyDAO.findEntries(firstResult, maxResults);
	}

	/* (non-Javadoc)
	 * @see sk.funix.userstory.service.impl.StoryService#countAllStorys()
	 */
	@Transactional(readOnly = true)
	public long countAllStories() {
		return storyDAO.countAll();
	}
	
	@Transactional(readOnly = true)
	public long countAllStoriesByUser(User user) {
		checkSecurity(user);
		return storyDAO.countAllByUser(user);
	}

	private void checkSecurity(User user){
		final User userConnected = SecurityUtil.getUserConnected();
		if (user.equals(userConnected) 
				&& !SecurityUtil.isUserConnectedAdmin()){
			throw new AuthorizationServiceException("Non authorized for this operation");
		}
	}
}
